package cn.wgx.module.mind.util;

import cn.wgx.common.base.BaseLogger;
import cn.wgx.common.base.IBaseController;
import cn.wgx.common.entity.mind.MindBaseEntity;
import cn.wgx.common.security.client.config.entity.LoginAppUser;
import cn.wgx.common.security.util.SysUserUtil;
import cn.wgx.module.mind.service.BaseMindService;
import cn.wgx.module.mind.service.ProjectRoleService;
import cn.wgx.module.mind.web.*;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.naming.NoPermissionException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 项目文件权限验证器
 */
@Aspect
@Component
public class MindProjectPermissionUtil extends BaseLogger {

    @Autowired
    private ProjectRoleService projectRoleService;

    //权限检测范围类
    private List<Class> projectRoleAll = new ArrayList() {{
        add(ProjectCtrl.class);
        add(ProjectRoleCtrl.class);
        add(ProjectUserCtrl.class);
        add(ProjectUserRoleCtrl.class);
    }};
    private List<Class> projectRoleSub = new ArrayList() {{
        add(ProjectRoleCtrl.class);
        add(ProjectUserCtrl.class);
        add(ProjectUserRoleCtrl.class);
    }};

    private List<Class> projectEle = new ArrayList() {{
        add(BeatCtrl.class);
        add(BlockCtrl.class);
        add(ChannelCtrl.class);
        add(DivideCtrl.class);
        add(GroupCtrl.class);
        add(HeadCtrl.class);
        add(LinkCtrl.class);
        add(ModCtrl.class);
    }};

    //需要拦截修改相关
    @Pointcut("execution(* cn.wgx.common.base.IBaseController+.add*(..)) || " +
            "execution(* cn.wgx.module.mind.web.*.add*(..))")
    public void add() {
    }

    @Pointcut("execution(* cn.wgx.common.base.IBaseController+.update*(..)) ||" +
            "execution(* cn.wgx.module.mind.web.*.update*(..))")
    public void modify() {
    }

    @Pointcut("execution(* cn.wgx.common.base.IBaseController+.del*(..)) ||" +
            "execution(* cn.wgx.module.mind.web.*.del*(..))")
    public void del() {
    }

    @Pointcut("execution(* cn.wgx.common.base.IBaseController+.get*(..)) "
            + "|| execution(* cn.wgx.common.base.IBaseController+.list*(..)) "
            + "|| execution(* cn.wgx.module.mind.web.*.list*(..))) "
            + "|| execution(* cn.wgx.module.mind.web.*.get*(..))) "
    )
    public void look() {
    }


    //检测"查"权限
    @Before("look()")
    public void beforeLook(JoinPoint joinPoint) throws NoPermissionException {
        if (!isMindProject(joinPoint)) {
            return;
        }
        //检测list是否带参数pro_id
        String name = joinPoint.getSignature().getName();
        if (name.startsWith("list")) {
            Object target = joinPoint.getTarget();
            for (Class clazz : projectEle) {
                if (clazz.isInstance(target)) {
                    Object[] args = joinPoint.getArgs();
                    for (Object o : args) {
                        if (o instanceof MindBaseEntity) {
                            if (((MindBaseEntity) o).getPro_id() == null) {
                                throw new NoPermissionException("缺少参数pro_id");
                            }
                        }
                    }
                }
            }
        }
    }

    //检测"增"权限
    @Before("add()")
    public void beforeAdd(JoinPoint joinPoint) throws NoPermissionException {
        if (!isMindProject(joinPoint)) {
            return;
        }
        c(projectRoleSub, projectEle, joinPoint, "只有创建人可以新增", "无权新增");
//        Integer pro_id = getProIdById(joinPoint.getTarget(), joinPoint.getArgs(), ((MethodSignature)joinPoint.getSignature()).getParameterNames());
//        if(!checkProjectPer(projectRoleSub, joinPoint.getTarget(), pro_id)){
//            throw new NoPermissionException("只有创建人可以新增");
//        }
//        if(!checkProjectPer(projectEle, joinPoint.getTarget(), pro_id)){
//            throw new NoPermissionException("无权新增");
//        }

    }

    //检测"改"权限
    @Before("modify()")
    public void beforeModify(JoinPoint joinPoint) throws NoPermissionException {
        if (!isMindProject(joinPoint)) {
            return;
        }

        c(projectRoleAll, projectEle, joinPoint, "只有创建人可以修改", "无权修改此数据");
//        Integer pro_id = getProIdById(joinPoint.getTarget(), joinPoint.getArgs(), ((MethodSignature)joinPoint.getSignature()).getParameterNames());
//        if(!checkProjectPer(projectRoleAll, joinPoint.getTarget(), pro_id)){
//            throw new NoPermissionException("只有创建人可以修改");
//        }
//        if(!doCheckModifyPermission(projectEle, joinPoint.getTarget(), pro_id)){
//            throw new NoPermissionException("无权修改此数据");
//        }
    }

    //检测"删"权限
    @Before("del()")
    public void beforeDel(JoinPoint joinPoint) throws NoPermissionException {
        if (!isMindProject(joinPoint)) {
            return;
        }
        c(projectRoleAll, projectEle, joinPoint, "只有创建人可以删除", "无权删除此数据");
//        Integer pro_id = getProIdById(joinPoint.getTarget(), joinPoint.getArgs(),((MethodSignature)joinPoint.getSignature()).getParameterNames());
//        if(!checkProjectPer(projectRoleAll, joinPoint.getTarget(), pro_id)){
//            throw new NoPermissionException("只有创建人可以删除");
//        }
//        if(!doCheckModifyPermission(projectEle, joinPoint.getTarget(), pro_id)){
//            throw new NoPermissionException("无权删除此数据");
//        }
    }

    private void c(List<Class> classes, List<Class> classes2, JoinPoint joinPoint, String e1, String e2) throws NoPermissionException {
        //检测需要创建人才能修改的数据
        if (!checkIsCreater(classes, joinPoint.getTarget(), joinPoint)) {
            throw new NoPermissionException(e1);
        }
        //检测需要授权的权限才能修改的数据
        if (!doCheckModifyPermission(classes2, joinPoint.getTarget(), joinPoint)) {
            throw new NoPermissionException(e2);
        }
    }

    private Integer getProIdById(Object target, Object[] params, String[] paramName) {
        if (target instanceof IBaseController) {
            IBaseController controller = (IBaseController) target;
            try {
                Field service = controller.getClass().getSuperclass().getDeclaredField("service");
                service.setAccessible(true);
                Object o = service.get(controller);
                if (o instanceof BaseMindService) {
                    BaseMindService baseMindService = (BaseMindService) o;
                    for (int i = 0, n = paramName.length; i < n; i++) {
                        if (paramName[i].equals("pro_id")) {
                            return (Integer) params[i];
                        }
                    }
                    for (Object param : params) {
                        if (param instanceof Integer) {
                            return baseMindService.getProIdById((Integer) param);
                        } else if (param instanceof MindBaseEntity) {
                            return baseMindService.getProIdByT((MindBaseEntity) param);
                        } else if (param instanceof Collection) {
                            for (Object o1 : (Collection) param) {
                                if (o1 instanceof MindBaseEntity) {
                                    return baseMindService.getProIdByT((MindBaseEntity) o1);
                                }
                            }
                        }
                    }
                }
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    //判断是否为mind模块下的方法
    private boolean isMindProject(JoinPoint joinPoint) {
        Class<?> targetClass = AopUtils.getTargetClass(joinPoint.getTarget());
        String className = targetClass.getName();
        if (className.startsWith("cn.wgx.module.mind.web.")) {
            return true;
        }
        return false;
    }

    //检测项目/项目角色/项目人员操作权限,只有创建人可以进行的操作
    private boolean checkIsCreater(List<Class> classList, Object ctl, JoinPoint joinPoint) {
        //属于待选的才判定
        for (Class clazz : classList) {
            if (clazz.isInstance(ctl)) {
                Integer pro_id = getProIdById(joinPoint.getTarget(), joinPoint.getArgs(), ((MethodSignature) joinPoint.getSignature()).getParameterNames());
                if(pro_id == null){
                    return false;
                }
                return ProjectUtil.isCreateUser(pro_id);
            }
        }
        return true;
    }

    //检测权限
    public boolean doCheckModifyPermission(List<Class> classList, Object ctl, JoinPoint joinPoint) {
        for (Class clazz : classList) {
            if (clazz.isInstance(ctl)) {
                Integer pro_id = getProIdById(joinPoint.getTarget(), joinPoint.getArgs(), ((MethodSignature) joinPoint.getSignature()).getParameterNames());
                if (pro_id == null) {
                    return false;
                }
                LoginAppUser loginAppUser = SysUserUtil.getLoginAppUser();
                if (loginAppUser == null) {
                    return false;
                }
                return projectRoleService.checkModifyP(pro_id, loginAppUser.getUser_id());
            }
        }
        return true;
    }


}
